package com.rivues.util.service.system;

import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.log4j.spi.LoggingEvent;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.rivues.core.RivuDataContext;
import com.rivues.module.platform.web.model.Log;
import com.rivues.module.platform.web.model.warning.SystemInfoBean;
import com.rivues.util.RivuTools;
import com.rivues.util.log.Logger;
import com.rivues.util.log.LoggerFactory;
import com.rivues.util.service.data.RequestStaticisBean;
import com.rivues.util.service.monitor.BusinessService;

@Component
public class DataPersistenceService extends BusinessService{
	private static Logger log = LoggerFactory.getLogger(DataPersistenceService.class) ;
	private static boolean taskRunning = false ;
	private static final BlockingQueue<Object> monitorEventQueue = new LinkedBlockingQueue<Object>();
	/**
	 * 服务名称
	 */
	public String getName(){
		return RivuDataContext.ServiceTypeName.LOG.toString();
	}
	@SuppressWarnings("unchecked")
	@Scheduled(fixedRate = 1000*5 )  
	public void service() throws IllegalAccessException, InvocationTargetException{
		log.info("启动日志服务，开始记录日志...，当前缓存的日志数量为："+monitorEventQueue.size(), "SYSTEM", "SYSTEM") ;
		
		/**
		 * 最大缓存的日志数量不超过1000，超过即清除
		 */
		RivuTools.processPersistenceLog(monitorEventQueue) ;
		
		while (RivuDataContext.isStart() && !taskRunning) {
			taskRunning = true ;
			RequestStaticisBean staticisBean = RivuDataContext.getStaticServiceMap().get(this.getName()) ;
			long start = System.currentTimeMillis() ;
			long times = 0 ;
			try {
				/**
				 * 系统的数据持久化服务服务在启动后才可用，再次之前，系统硬件信息已经开始记录，在此过程中，无法获取系统的不可用时间，
				 * 所以，在启动以后找到上次服务器启动以来的最后一次记录，然后使用本次启动的第一次记录 减去上次最后一次记录的时间即为 不可用时间。
				 */
				if(SystemMonitorService.getLastInfoBean()==null){
					SystemMonitorService.setLastInfoBean(getLastSystemInfo()) ;
				}
				if(SystemMonitorService.getFirstInfoBean()!=null && SystemMonitorService.getLastInfoBean()!=null && SystemMonitorService.getFirstInfoBean().getId()==null){
					/**
					 * 记录不可用时间，去掉5秒的检测频率时间
					 */
					SystemMonitorService.getFirstInfoBean().setUnavailabletime(SystemMonitorService.getFirstInfoBean().getCreatedate().getTime() - SystemMonitorService.getLastInfoBean().getCreatedate().getTime() - 5000) ; 
					if((SystemMonitorService.getFirstInfoBean().getUpdatetime().getTime()-SystemMonitorService.getLastInfoBean().getUpdatetime().getTime())>5000){
						SystemMonitorService.getFirstInfoBean().setUnavailabletype(RivuDataContext.UnavailableTypeEnum.SERVERDOWN.toString()) ;
						SystemMonitorService.getFirstInfoBean().setServerdowntime(SystemMonitorService.getFirstInfoBean().getUpdatetime().getTime()-SystemMonitorService.getLastInfoBean().getCreatedate().getTime()) ;
					}else{
						SystemMonitorService.getFirstInfoBean().setUnavailabletype(RivuDataContext.UnavailableTypeEnum.SERVICEDOWN.toString()) ;
					}
				}
				/**
				 * 数据记录 持久化
				 */
				Object data = monitorEventQueue.take() ; 
				if(staticisBean!=null){
		    		staticisBean.setWaittingtime(System.currentTimeMillis() - start);
				}
				start = System.currentTimeMillis() ;
				/**
				 * 将ID设置为Null,避免出现 重复ID的现象
				 */
				BeanUtils.setProperty(data, "id", null) ;
				/**
				 * 以下代码注释掉， 所有的审计记录都继承自超类 MonitorBean ， 并通过MonitorBean 实现预警
				 */
				boolean writeLog = true ;
				if(data!=null && data instanceof Log){
					Log logEvent = (Log) data ;
					if(!RivuTools.outputLog(logEvent.getLevels(), logEvent.getOrgi())){
						writeLog = false ;
					}
				}
				if(writeLog){
					RivuDataContext.getService().saveIObject(data) ;
				}
				if(staticisBean!=null){
					times = System.currentTimeMillis() - start ;
		    		staticisBean.setSuccessrequest(1) ;
		    		staticisBean.setSuccesstime(times) ;
		    		if(times > staticisBean.getSuccessmaxtime()){
		    			staticisBean.setSuccessmaxtime(times) ;
		    		}
		    		if(times < staticisBean.getSuccessmintime() || staticisBean.getSuccessmintime() == 0){
		    			staticisBean.setSuccessmintime(times) ;
		    		}
				}
			} catch (InterruptedException ie) {
				times = System.currentTimeMillis() - start ;
				staticisBean.setFaildrequest(1) ;
				staticisBean.setFaildtime(times) ;
				if(times > staticisBean.getFaildmaxtime()){
					staticisBean.setFaildmaxtime(times) ;
				}
				if(times < staticisBean.getFaildmintime() || staticisBean.getFaildmintime() == 0 ){
					staticisBean.setFaildmintime(times) ;
				}
				ie.printStackTrace();
			}finally{
				taskRunning = false ;
				staticisBean.setServicetimes(1) ;
				staticisBean.setRunningtime(times) ;
				if(times > staticisBean.getMaxrequesttime()){
					staticisBean.setMaxrequesttime(times) ;
				}
				if(staticisBean.getMinrequesttime()==0 || times < staticisBean.getMinrequesttime()){
					staticisBean.setMinrequesttime(times) ;
				}
			}
		}
	}
	/**
	 * 获取最后一条系统设备信息日志记录
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static SystemInfoBean getLastSystemInfo(){
		List<SystemInfoBean> beanList = null ;
		if(RivuDataContext.getWebApplicationContext()!=null){
			beanList = RivuDataContext.getService().findPageByCriteria(DetachedCriteria.forClass(SystemInfoBean.class).addOrder(Order.desc("createdate")), 1, 1) ;
		}
		return beanList.size()>0 ? beanList.get(0) : null  ;
	}
	/**
	 * 日志记录接口
	 * @param data
	 */
	public static void persistence(Object data){
		monitorEventQueue.add(data) ;
	}
}
